import { filesize } from "filesize";
import { getFileIcon } from '@/lib/file-icon';
import { formatDateZhCn, createModal } from '@/lib/utils';
import { getFileExtension, previewableExtensions } from './file-type';
import type { FileType } from "./file-type";

export interface File {
    name: string,
    size: number,
    uploaded_at: string,
    url: string,
    type?: string,
}

export function setupFilelist(
    element: HTMLElement,
    initial_files: File[],
): void {
    const containerElem = document.createElement("div");
    containerElem.classList.add("tw:overflow-x-auto", "tw:max-w-screen-md");
    containerElem.innerHTML = `
<table class="tw:table">
  <thead>
    <tr>
      <th>${gettext("文件名")}</th>
      <th>${gettext("大小")}</th>
      <th>${gettext("上传时间")}</th>
    </tr>
    </thead>
    <tbody>
    </tbody>
</table>
`;
    const tbodyElem = containerElem.querySelector("tbody")!;
    initial_files?.forEach(file => {
        const trElem = document.createElement("tr");
        trElem.classList.add("tw:cursor-pointer");
        trElem.setAttribute("data-url", file.url);
        trElem.setAttribute("data-filename", file.name);
        trElem.setAttribute("role", "button");

        const uploaded_at = formatDateZhCn(file.uploaded_at);

        const fileIcon = getFileIcon({
            filename: file.name,
            contentType: file.type,
            iconClass: 'tw:size-4'
        });

        
        trElem.innerHTML = `
<th class='tw:flex tw:gap-2'>${fileIcon}${file.name}</th>
<th>${filesize(file.size)}</th>
<th>${uploaded_at}</th>
`;
        tbodyElem.append(trElem);
    });
    
    // Replace the element
    element.replaceWith(containerElem);

    // Use event delegation on the container
    containerElem.addEventListener("click", (event) => {
        const trElement = (event.target as HTMLElement).closest('tr[data-url]');
        if (trElement) {
            const url = trElement.getAttribute('data-url')!;
            const filename = trElement.getAttribute('data-filename')!;
            handleFileAction(url, filename);
        }
    });
}

interface PreviewableFile {
    url: string;
    filename?: string;
    type: FileType | null;
    isPreviewable: boolean;
}

export class FileHandler {

    private static checkPreviewability(url: string, filename: string): PreviewableFile {
        const extension = getFileExtension(filename);
        
        // Check if the file has a previewable extension and is not a PDF
        // NOTE PDF is not implemented
        if (extension && extension in previewableExtensions && previewableExtensions[extension] !== 'pdf') {
            return {
                url: url,
                filename: filename,
                type: previewableExtensions[extension],
                isPreviewable: true
            };
        }

        // Return non-previewable file info
        return {
            url: url,
            filename: filename,
            type: null,
            isPreviewable: false
        };
    }

    private static createPreviewElement(file: PreviewableFile): HTMLElement {
        const container = document.createElement('div');
        container.className = 'tw:flex tw:flex-col tw:gap-4';

        // Add actions
        const actionBarElem = document.createElement("div");
        actionBarElem.className = 'tw:flex tw:flex-row-reverse';
        const downloadBtn = document.createElement('button');
        downloadBtn.className = 'by6-crumbs-action-btn';
        downloadBtn.innerHTML = `${gettext('下载')}`;
        downloadBtn.onclick = () => this.downloadFile(file.url, file.filename);
        actionBarElem.appendChild(downloadBtn);
        
        container.appendChild(actionBarElem);

        // Create preview content
        const previewContainer = document.createElement('div');
        
        if (file.isPreviewable && file.type) {
            // Handle previewable files
            const elements: Partial<Record<FileType, () => HTMLElement>> = {
                image: () => {
                    const img = document.createElement('img');
                    img.className = 'tw:max-w-full tw:h-auto';
                    img.src = file.url;
                    return img;
                },
                video: () => {
                    const video = document.createElement('video');
                    video.className = 'tw:w-full';
                    video.controls = true;
                    video.src = file.url;
                    return video;
                },
                audio: () => {
                    const audio = document.createElement('audio');
                    audio.className = 'tw:w-full';
                    audio.controls = true;
                    audio.src = file.url;
                    return audio;
                },
            };

            const previewElement = elements[file.type]?.();
            if (previewElement) {
                previewContainer.appendChild(previewElement);
            } else {
                previewContainer.appendChild(this.createNonPreviewableMessage(file.url));
            }
        } else {
            // For non-previewable files, create a message with a link to open in new tab
            previewContainer.appendChild(this.createNonPreviewableMessage(file.url));
        }
        
        container.appendChild(previewContainer);
        return container;
    }

    private static createNonPreviewableMessage(url: string): HTMLElement {
        const div = document.createElement('div');
        div.className = 'tw:text-center tw:p-4';
        div.innerHTML = `
            <p class="tw:mb-4">${gettext('此文件无法在此预览')}</p>
            <a href="${url}" target="_blank" rel="noopener noreferrer" class="tw:btn tw:btn-neutral">
                ${gettext('在新标签页中打开')}
            </a>
        `;
        return div;
    }

    private static showPreviewModal(file: PreviewableFile): void {
        const previewElement = this.createPreviewElement(file);
        createModal({
            contentElem: previewElement,
        });
    }

    /**
     * NOTE filename mostly doesn't work if upstream set `Content-Disposition` header
     * In our case, it doesn't work.
     */
    public static downloadFile(url: string, filename?: string): void {
        const link = document.createElement('a');
    
        link.href = url;
        if (filename) {
            link.download = filename;
        }
        link.target = '_blank';
        link.rel = 'noopener noreferrer';
        link.click();
    }

    public static handleFile(url: string, filename: string): void {
        const file = this.checkPreviewability(url, filename);
        // Always show preview modal, regardless of previewability
        this.showPreviewModal(file);
    }
}

// Export the main handler function
export const handleFileAction = FileHandler.handleFile.bind(FileHandler);
